wayland: avoid jitter in keyboard repeat
authorChristian Hergert <chergert@redhat.com>
Tue, 26 Apr 2016 01:10:09 +0000 (18:10 -0700)
committerChristian Hergert <chergert@redhat.com>
Tue, 26 Apr 2016 01:15:24 +0000 (18:15 -0700)
When synthesizing keyboard repeat, we can potentially drift further from
the mark depending on the timing of the frame callback and how long it
took to deliver the event.

This patch attempts to reduce this by tracking from a stable epoch the
time of our next keyboard repeat.

https://bugzilla.gnome.org/show_bug.cgi?id=765567

gdk/wayland/gdkdevice-wayland.c

index 856437df51e99b1cb9225c1f52794968d6652c16..c6823c1a15c3fedefbd632607b4e8f758575ec4b 100644 (file)
@@ -177,6 +177,7 @@ struct _GdkWaylandSeat
   guint32 repeat_timer;
   guint32 repeat_key;
   guint32 repeat_count;
+  gint64 repeat_deadline;
   GSettings *keyboard_settings;
   uint32_t keyboard_time;
 
@@ -1815,6 +1816,9 @@ deliver_key_event (GdkWaylandSeat *seat,
   GdkKeymap *keymap;
   xkb_keysym_t sym;
   guint delay, interval, timeout;
+  gint64 begin_time, now;
+
+  begin_time = g_get_monotonic_time ();
 
   stop_key_repeat (seat);
 
@@ -1862,10 +1866,20 @@ deliver_key_event (GdkWaylandSeat *seat,
   seat->repeat_count++;
   seat->repeat_key = key;
 
+  interval *= 1000L;
+  delay *= 1000L;
+
+  now = g_get_monotonic_time ();
+
   if (seat->repeat_count == 1)
-    timeout = delay;
+    seat->repeat_deadline = begin_time + delay;
+  else if (seat->repeat_deadline + interval > now)
+    seat->repeat_deadline += interval;
   else
-    timeout = interval;
+    /* frame delay caused us to miss repeat deadline */
+    seat->repeat_deadline = now;
+
+  timeout = (seat->repeat_deadline - now) / 1000L;
 
   seat->repeat_timer =
     gdk_threads_add_timeout (timeout, keyboard_repeat, seat);